package com.laolang.shop.modules.sys.logic.admin.impl;

import cn.hutool.core.collection.CollUtil;
import com.laolang.shop.modules.sys.entity.SysMenu;
import com.laolang.shop.modules.sys.entity.SysRole;
import com.laolang.shop.modules.sys.entity.SysUser;
import com.laolang.shop.modules.sys.logic.admin.SysUserAdminLogic;
import com.laolang.shop.modules.sys.pojo.vo.SysUserInfoVo;
import com.laolang.shop.modules.sys.service.SysRoleMenuService;
import com.laolang.shop.modules.sys.service.SysUserRoleService;
import com.laolang.shop.modules.sys.service.SysUserService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author khlbat
 * @version 1.0
 * @date 2020/11/1 20:46
 */
@Slf4j
@AllArgsConstructor
@Service
public class SysUserAdminLogicImpl implements SysUserAdminLogic {

    private final SysUserService sysUserService;

    private final SysUserRoleService sysUserRoleService;

    private final SysRoleMenuService sysRoleMenuService;

    @Override
    public SysUserInfoVo info(Long userId) {
        SysUserInfoVo vo = new SysUserInfoVo();
        vo.setUserInfo(getUserInfo(userId));
        vo.setRoleList(getRoleList(userId));
        vo.setMenuList(getMenuList(userId));
        return vo;
    }

    private SysUserInfoVo.UserInfo getUserInfo(Long userId) {
        SysUserInfoVo.UserInfo userinfo = new SysUserInfoVo.UserInfo();
        SysUser entity = sysUserService.getById(userId);
        userinfo.setUserId(userId);
        userinfo.setTenantId(entity.getTenantId());
        userinfo.setNickname(entity.getNickname());
        userinfo.setAvatar(entity.getAvatar());
        return userinfo;
    }

    private List<SysUserInfoVo.Role> getRoleList(Long userId) {
        List<SysUserInfoVo.Role> roleList = new ArrayList<>();
        List<SysRole> roles = sysUserRoleService.listByUserId(userId);
        if (CollUtil.isNotEmpty(roles)) {
            roleList = roles.stream().map(sysRole -> {
                SysUserInfoVo.Role r = new SysUserInfoVo.Role();
                r.setId(sysRole.getId());
                r.setCode(sysRole.getCode());
                return r;
            }).collect(Collectors.toList());
        }
        return roleList;
    }

    private List<SysUserInfoVo.Menu> getMenuList(Long userId) {
        List<SysMenu> entityList = sysRoleMenuService.listByUserId(userId);
        if (CollUtil.isEmpty(entityList)) {
            return new ArrayList<>();
        }

        List<SysUserInfoVo.Menu> tree = entityList.stream()
                .filter(entity -> 0L == entity.getParentId())
                .map(this::menuEntity2vo)
                .collect(Collectors.toList());

        Map<Long, SysUserInfoVo.Menu> treeMap = tree.stream().collect(Collectors.toMap(SysUserInfoVo.Menu::getId, t -> t));

        List<SysMenu> notRootList = entityList.stream()
                .filter(t -> 0L != t.getParentId())
                .sorted(Comparator.comparing(SysMenu::getParentId).thenComparing(SysMenu::getSort))
                .collect(Collectors.toList());

        if (CollUtil.isNotEmpty(notRootList)) {
            for (SysMenu entity : notRootList) {
                SysUserInfoVo.Menu parent = treeMap.get(entity.getParentId());
                if (null != parent) {
                    if (null == parent.getChildren()) {
                        parent.setChildren(new ArrayList<>());
                    }
                    SysUserInfoVo.Menu vo = menuEntity2vo(entity);
                    parent.getChildren().add(vo);
                    treeMap.put(vo.getId(), vo);
                }
            }
        }

        return tree;
    }

    private SysUserInfoVo.Menu menuEntity2vo(SysMenu entity) {
        SysUserInfoVo.Menu vo = new SysUserInfoVo.Menu();
        vo.setId(entity.getId());
        vo.setName(entity.getName());
        vo.setParentId(entity.getParentId());
        vo.setUrl(entity.getUrl());
        vo.setChildren(new ArrayList<>());
        vo.setSort(entity.getSort());
        vo.setCode(entity.getCode());
        return vo;
    }


}
